package com.platform.qujia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.platform.qujia.dao.ReceiptSectionMapper;
import com.platform.qujia.enums.PrintEnum;
import com.platform.qujia.enums.ReceiptType;
import com.platform.qujia.pojo.ReceiptSection;
import com.platform.qujia.pojo.ReceiptSectionField;
import com.platform.qujia.service.IReceiptSectionFieldService;
import com.platform.qujia.service.IReceiptSectionService;
import com.platform.qujia.utils.FreeMarkerUtil;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.Writer;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @date 2024/1/24
 */
@Service
public class ReceiptSectionServiceImpl extends ServiceImpl<ReceiptSectionMapper, ReceiptSection> implements IReceiptSectionService {

    private static final Logger log = LoggerFactory.getLogger(ReceiptSectionServiceImpl.class);

    public static final long DEFAULT_ENTERPRISE_ID = 0L;

    @Autowired
    private IReceiptSectionFieldService receiptSectionFieldService;
    @Autowired
    private FreeMarkerUtil freeMarkerUtil;

    @Override
    public List<ReceiptSection> queryAllReceiptSectionWithField(Long enterpriseId, ReceiptType receiptType) {
        LambdaQueryWrapper<ReceiptSection> receiptSectionQw = Wrappers.lambdaQuery(ReceiptSection.class);
        receiptSectionQw.eq(ReceiptSection::getReceiptType, receiptType)
                .and(i -> i.eq(ReceiptSection::getEnterpriseId, enterpriseId).or().eq(ReceiptSection::getEnterpriseId, DEFAULT_ENTERPRISE_ID))
                .orderByAsc(ReceiptSection::getEnterpriseId);
        List<ReceiptSection> sectionList = this.list(receiptSectionQw);
        sectionList = new ArrayList<>(sectionList.stream().collect(Collectors.toMap(ReceiptSection::getSectionName, re -> re, (u, v) -> v, HashMap::new)).values());
        sectionList.sort(Comparator.comparingInt(ReceiptSection::getSectionOrder));
        LambdaQueryWrapper<ReceiptSectionField> receiptSectionFieldQw = Wrappers.lambdaQuery(ReceiptSectionField.class);
        receiptSectionFieldQw.eq(ReceiptSectionField::getReceiptType, receiptType)
                .and(i -> i.eq(ReceiptSectionField::getEnterpriseId, enterpriseId).or().eq(ReceiptSectionField::getEnterpriseId, DEFAULT_ENTERPRISE_ID))
                .orderByAsc(ReceiptSectionField::getEnterpriseId);
        List<ReceiptSectionField> fieldList = receiptSectionFieldService.list(receiptSectionFieldQw);
        Map<String, List<ReceiptSectionField>> filedsMap = fieldList.stream()
                .collect(Collectors.toMap(rf -> rf.getSectionName() + rf.getFieldName(), rf -> rf, (u, v) -> v, HashMap::new))
                .values()
                .stream()
                .sorted(Comparator.comparingInt(ReceiptSectionField::getFieldOrder))
                .collect(Collectors.groupingBy(ReceiptSectionField::getSectionName,
                        Collectors.mapping(rf -> {
                            if (rf.getEnterpriseId() == 0) {
                                rf.setId(null);
                                rf.setEnterpriseId(null);
                                rf.setSectionId(null);
                            }
                            return rf;
                        }, Collectors.toList())));
        for (ReceiptSection receiptSection : sectionList) {
            receiptSection.setFieldList(filedsMap.get(receiptSection.getSectionName()));
            if (receiptSection.getEnterpriseId() == 0) {
                receiptSection.setId(null);
                receiptSection.setEnterpriseId(null);
            }
        }
        return sectionList;
    }

    @Override
    public void mergeTemplate(Long enterpriseId, ReceiptType receiptType, PrintEnum printEnum, Map<String,Object> context, Writer writer) {
        List<ReceiptSection> receiptSections = this.queryAllReceiptSectionWithField(enterpriseId, receiptType);
        context.put("sections", receiptSections);
        try {
            freeMarkerUtil.process(getTemplatePath(printEnum,receiptType),context,writer);
        } catch (TemplateException | IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    private String getTemplatePath(PrintEnum printEnum, ReceiptType receiptType) {
        StringBuilder builder = new StringBuilder("templates");
        switch (printEnum){
            case FEIE:
                builder.append("/feie");
                break;
            case YILIANYUN:
                builder.append("/yilianyun");
                break;
            case YILIANYUNK4:
                builder.append("/yilianyunk4");
                break;
            case POS:
                builder.append("/pos");
                break;
        }
        switch (receiptType){
            case CONSUME_MERCHANT_UNION:
                builder.append("/consumeMerchant");
                break;
            case CONSUME_CUSTOMER_UNION:
                builder.append("/consumeCustomer");
                break;
            case CLASS_SETTLEMENT:
                builder.append("/classSettlement");
                break;
        }
        return builder.append("/index.ftl").toString();
    }

}
